import { defineStore } from 'pinia'
import { v4 as uuidv4 } from 'uuid'
// import { textDefaultProps } from '@/defaultProps'
import type { IPageProps } from '@/defaultProps'
import { cloneDeep, isEmpty } from 'lodash-es'
import { message } from 'ant-design-vue'
import { type IHistoryProps, type ISaveTemplateProps } from './type/editor'
import { insertAt } from '@/helper'
import type { AllComponentProps } from 'lego-bricks'
import { getWorkDtailAPI, updateWorkAPI } from '@/request/modules/work'
const pageDefaultProps: Partial<IPageProps> = {
  backgroundColor: '#ffffff',
  backgroundImage: '',
  backgroundRepeat: 'no-repeat',
  backgroundSize: 'cover',
  height: '560px',
}
//方向
type Direction = 'Up' | 'Right' | 'Down' | 'Left'
// 定义一个防抖函数，用于延迟执行回调函数
const debounceChange = (callBack: (...arg: any) => void, timeout = 1000) => {
  let timer = 0
  // 返回一个新的函数，该函数会在指定的时间间隔后执行回调函数
  return (...arg: any) => {
    // 清除之前的定时器
    clearTimeout(timer)
    // 设置新的定时器
    timer = setTimeout(() => {
      callBack(...arg)
    }, timeout)
  }
}
// 将历史记录推入历史列表
const pushHistory = (state: any, historyRecord: IHistoryProps) => {
  // 如果当前历史索引不为-1，则将历史列表截取到当前索引，并将当前索引置为-1
  if (state.historyIndex !== -1) {
    state.historyList = state.historyList.slice(0, state.historyIndex)
    state.historyIndex = -1
  }

  // 如果历史列表长度小于最大长度，则将历史记录推入历史列表
  if (state.historyList.length < state.historyMaxlength) {
    state.historyList.push(historyRecord)
  } else {
    // 否则，将历史列表的第一个元素移除，并将历史记录推入历史列表
    state.historyList.shift()
    state.historyList.push(historyRecord)
  }
}
// 将修改历史记录推入历史列表
const pushModifyHistory = (
  state: any,
  {
    componentId = '',
    key,
    oldVal,
    value,
    type = '',
  }: {
    componentId: string
    key: string
    oldVal: any
    value: any
    type: string
  }
) => {
  // 创建历史记录对象
  const historyInfo: IHistoryProps = {
    type: 'update',
    componentId: componentId,
    id: uuidv4(),
    data: {
      key,
      oldVal,
      newVal: value,
      type,
    },
  }
  // 将历史记录推入历史列表
  pushHistory(state, historyInfo)
  // 将缓存的老值置为null
  state.cacheOldVAlue = null
}
// 使用防抖函数包装pushModifyHistory函数
const pushModifyHistoryDebounce = debounceChange(pushModifyHistory, 300)

const useEditorStore = defineStore('editor', {
  state: () => {
    return {
      testComponents: [] as any[],
      currentComponentId: '',
      /**页面数据 */
      pageData: {
        title: '',
        props: cloneDeep(pageDefaultProps),
        id: -1,
        desc: '',
        coverImg: '',
      },
      /**复制组件 */
      copyComponent: {} as any,
      /**操作步骤数组*/
      historyList: [] as IHistoryProps[],
      /**当前操作步骤索引 */
      historyIndex: -1,
      /**缓存oldVal */
      cacheOldVAlue: null as any,
      /**缓存操作数组的最大长度 */
      historyMaxlength: 80,
      /**是否开启自动保存 */
      isAutoSave: false,
      workId: '',
    }
  },
  actions: {
    setWorkId(id: string) {
      this.workId = id
    },
    //设置图层zindex
    setLayerZIndex() {
      this.testComponents.forEach((item, index) => {
        Reflect.set(item, 'zIndex', index + 1)
      })
    },
    //保存模板信息
    async saveTemplateInfo(workId: string) {
      const { props, ...res } = this.pageData
      const data: ISaveTemplateProps = {
        ...res,
        content: {
          components: this.testComponents,
          props,
        },
      }
      await updateWorkAPI(workId, data)
      this.isAutoSave = false
    },
    //获取模板详情
    async getTemplateDetail(workId: string) {
      const result = (await getWorkDtailAPI(workId)).data
      const { components, props } = result?.data?.content || {}
      this.testComponents =
        components?.map((item) => {
          if (item.props.imageSrc && !item.src) {
            Reflect.set(item.props, 'src', item.props.imageSrc)
          }
          if (typeof item.props.opacity === 'number') {
            Reflect.set(item.props, 'opacity', item.props.opacity + '')
          }
          return item
        }) || []
      //设置组件层级
      this.setLayerZIndex()

      this.pageData.props = props || cloneDeep(pageDefaultProps)
      const { title, desc, coverImg, id } = result.data || {}

      this.pageData.title = title
      this.pageData.desc = desc
      this.pageData.coverImg = coverImg
      this.pageData.id = id
    },
    // 添加组件
    addComponent(data: any) {
      this.isAutoSave = true
      // 将传入的data添加到testComponents数组中
      this.testComponents.push(data)
      this.setLayerZIndex()
      // 创建一个IHistoryProps类型的historyInfo对象
      const historyInfo: IHistoryProps = {
        // 设置type为add
        type: 'add',
        // 设置componentId为data的id
        componentId: data.id,
        // 设置data为data的深拷贝
        data: cloneDeep(data),
        // 设置id为uuidv4生成的唯一标识
        id: uuidv4(),
      }
      // 调用pushHistory函数，将historyInfo对象传入
      pushHistory(this, historyInfo)
      //设置组件层级
      this.setLayerZIndex()
    },
    // 根据id删除组件
    removeElement(id: string) {
      // 过滤掉id与传入id相同的组件
      this.testComponents = this.testComponents.filter((item) => item.id !== id)
      this.isAutoSave = true
    },
    setActiveComponent(id: string) {
      this.currentComponentId = id
    },
    /**
     *
     * @param param { key: string | number; value: any } 只要包含key和value即可
     * @param isRoot 修改根节点信息或者修改props中的信息区分，true为修改根节点信息，false为修改props中的信息
     */
    // 修改当前组件的属性
    changeCurrentComponentProps<T extends { key: string | number; value: any }>(
      { key, value }: T,
      isRoot = false
    ) {
      this.isAutoSave = true
      // 获取当前组件
      const curComponent: any = this.testComponents.find(
        (item) => item.id === this.currentComponentId
      )
      // 如果当前组件存在
      if (curComponent) {
        // 如果是根组件
        if (isRoot) {
          curComponent[key] = value
        } else {
          // 获取当前属性的旧值
          const oldVal = curComponent.props[key]
          // 如果缓存旧值不存在，则将旧值存入缓存
          if (this.cacheOldVAlue === null) {
            this.cacheOldVAlue = oldVal
          }
          // 修改当前属性的值
          curComponent.props[key] = value
          // 将修改记录加入修改历史
          pushModifyHistoryDebounce(this, {
            componentId: curComponent.id,
            key,
            oldVal: this.cacheOldVAlue,
            value,
          })
        }
      }
    },
    /**修改页面层级 */
    // 修改页面数据
    changePageData(
      { key, value }: { key: keyof IPageProps | string; value: any },
      isRoot = false
    ) {
      this.isAutoSave = true
      if (isRoot) {
        const rootKey = key as string
        Reflect.set(this.pageData, rootKey, value)
      } else {
        const keys = key as keyof IPageProps
        // 获取旧值
        const oldValue = this.pageData.props[keys]
        // 如果缓存旧值不存在，则将旧值存入缓存
        if (this.cacheOldVAlue === null) {
          this.cacheOldVAlue = oldValue
        }
        // 将新值赋给页面数据
        this.pageData.props[keys] = value
        // 将修改记录加入修改历史
        pushModifyHistoryDebounce(this, {
          componentId: '',
          key,
          oldVal: this.cacheOldVAlue,
          value,
          type: 'page',
        })
      }
    },
    /**元素移动以及拖动元素四角改变大小 */
    // 修改组件移动位置
    changeMovePosition(
      { key, value }: { key: string | string[]; value: string | string[] },
      id: string
    ) {
      // 根据id找到当前组件
      const curComponent: any = this.testComponents.find(
        (item) => item.id === id
      )
      // 如果找到了当前组件
      if (curComponent) {
        // 如果key是数组，则将当前组件的props中对应key的值取出，否则将value赋值给oldVal
        const oldVal = Array.isArray(key)
          ? key.map((k) => curComponent.props[k])
          : value
        // 创建历史记录信息
        const historyInfo: IHistoryProps = {
          type: 'update',
          componentId: curComponent.id,
          id: uuidv4(),
          data: {
            key,
            oldVal,
            newVal: value,
          },
        }
        // 将历史记录信息推入历史记录栈中
        pushHistory(this, historyInfo)

        // 如果key和value都是数组，则将key和value中的值分别赋值给当前组件的props中对应key的值
        if (Array.isArray(key) && Array.isArray(value)) {
          key.forEach((item, index) => {
            curComponent.props[item] = value[index]
          })
          // 如果key和value都是字符串，则将value赋值给当前组件的props中对应key的值
        } else if (typeof key === 'string' && typeof value === 'string') {
          curComponent.props[key] = value
        }
        this.isAutoSave = true
      }
    },
    //复制组件
    //复制组件
    copyComponentHandle(id: string) {
      //根据id查找当前组件
      const curComponent = this.testComponents.find(
        (compoennt) => compoennt.id === id
      )
      //如果找到了当前组件
      if (curComponent) {
        //将当前组件赋值给copyComponent
        this.copyComponent = curComponent
        //提示复制成功
        message.success('复制当前图层成功')
      }
    },
    //粘贴组件
    pasteComponent() {
      //如果copyComponent不为空
      if (!isEmpty(this.copyComponent)) {
        //克隆copyComponent
        const clonedComponent = cloneDeep(this.copyComponent)
        //生成新的id
        clonedComponent.id = uuidv4()
        //将layerName加上副本
        clonedComponent.layerName = clonedComponent.layerName + '副本'
        //将克隆的组件添加到testComponents中
        this.testComponents.push(clonedComponent)
        //提示粘贴成功
        message.success('粘贴当前图层成功')
        //生成历史记录
        const historyInfo: IHistoryProps = {
          type: 'add',
          componentId: clonedComponent.id,
          data: cloneDeep(clonedComponent),
          id: uuidv4(),
        }
        //将历史记录添加到历史记录栈中
        pushHistory(this, historyInfo)
      }
      this.isAutoSave = true
    },
    //删除组件
    deleteComponentHandle(id: string) {
      // 根据id找到组件在数组中的索引
      const index = this.testComponents.findIndex((item) => item.id === id)
      // 创建历史记录对象
      const historyInfo: IHistoryProps = {
        type: 'delete',
        componentId: id,
        data: this.CurrentComponent,
        id: uuidv4(),
        index,
      }
      // 将历史记录对象推入历史记录数组
      pushHistory(this, historyInfo)
      // 根据id过滤出不需要删除的组件
      this.testComponents = this.testComponents.filter((item) => item.id !== id)
      // 弹出删除成功的提示信息
      message.success('删除当前图层成功')
      this.isAutoSave = true
    },
    //根据按键移动组件
    // 根据传入的参数移动组件
    moveComponentByKey(data: {
      direction: Direction
      id: string
      moveSize: number
    }) {
      // 解构传入的参数
      const { direction, id, moveSize } = data
      // 根据id找到对应的组件
      const curComponent = this.testComponents.find((item) => item.id === id)
      // 如果找到了对应的组件
      if (curComponent) {
        // 获取组件的top和left属性
        const oldTop = parseInt(curComponent.props.top)
        const oldLeft = parseInt(curComponent.props.left)
        // 根据传入的方向进行移动
        switch (direction) {
          case 'Up':
            // 向上移动
            this.changeMovePosition(
              { key: 'top', value: oldTop - moveSize + 'px' },
              id
            )
            break
          case 'Down':
            // 向下移动
            this.changeMovePosition(
              { key: 'top', value: oldTop + moveSize + 'px' },
              id
            )
            break
          case 'Left':
            // 向左移动
            this.changeMovePosition(
              { key: 'left', value: oldLeft - moveSize + 'px' },
              id
            )
            break
          case 'Right':
            // 向右移动
            this.changeMovePosition(
              { key: 'left', value: oldLeft + moveSize + 'px' },
              id
            )
            break
          default:
            break
        }
      }
    },
    //撤销操作
    undo() {
      //从来没有操作过
      if (this.historyIndex === -1) {
        this.historyIndex = this.historyList.length - 1
      } else {
        if (this.historyIndex === 0) {
          message.info('已经是最早的操作了')
          return
        }
        //操作过就往前一个
        this.historyIndex--
      }
      //获取当前操作
      const historyInfo = this.historyList[this.historyIndex]
      if (historyInfo) {
        //开始判断
        switch (historyInfo.type) {
          case 'add': {
            //删除对应的组件
            this.testComponents = this.testComponents.filter(
              (item) => item.id !== historyInfo.componentId
            )
            break
          }
          case 'delete': {
            //添加对应的组件
            this.testComponents = insertAt(
              this.testComponents,
              historyInfo.index!,
              historyInfo.data
            )
            break
          }
          case 'update': {
            //更新对应的组件
            const { data, componentId } = historyInfo
            const { oldVal, key, type } = data

            if (type && type === 'page') {
              //更新页面数据
              this.pageData.props[key as keyof IPageProps] = oldVal
            } else {
              //更新组件数据
              const updatedComponent = this.testComponents.find(
                (item) => item.id === componentId
              )
              if (updatedComponent) {
                if (Array.isArray(key) && Array.isArray(oldVal)) {
                  //更新组件的多个属性
                  key.forEach((item, index) => {
                    updatedComponent.props[item as keyof AllComponentProps] =
                      oldVal[index]
                  })
                } else if (
                  typeof key === 'string' &&
                  typeof oldVal === 'string'
                ) {
                  //更新组件的单个属性
                  updatedComponent.props[key as keyof AllComponentProps] =
                    oldVal
                }
              }
            }

            break
          }
          default:
            break
        }
      }
      this.isAutoSave = true
      //设置组件层级
      this.setLayerZIndex()
    },
    //重做
    redo() {
      //从来没有操作过
      if (this.historyIndex === -1) {
        // 如果历史索引为-1，则返回
        return
      } else if (this.historyIndex === this.historyList.length) {
        // 如果历史索引等于历史列表的长度，则提示已经是最新的操作了
        message.info('已经是最新的操作了')
        return
      }

      // 获取历史信息
      const historyInfo = this.historyList[this.historyIndex]

      // 如果历史信息存在
      if (historyInfo) {
        // 获取历史信息中的数据
        const { data, componentId } = historyInfo

        // 根据历史信息的类型进行不同的操作
        switch (historyInfo.type) {
          case 'add': {
            // 如果类型是add，则将数据添加到testComponents中
            this.testComponents.push(data)
            break
          }
          case 'delete': {
            // 如果类型是delete，则从testComponents中删除对应id的组件
            this.testComponents = this.testComponents.filter(
              (item) => item.id !== componentId
            )
            break
          }
          case 'update': {
            // 如果类型是update，则更新testComponents中的组件
            const { newVal, key, type } = data
            if (type && type === 'page') {
              // 如果type是page，则更新pageData中的props
              this.pageData.props[key as keyof IPageProps] = newVal
            } else {
              // 否则，更新testComponents中的组件
              const updatedComponent = this.testComponents.find(
                (item) => item.id === componentId
              )
              if (updatedComponent) {
                if (Array.isArray(key) && Array.isArray(newVal)) {
                  // 如果key和newVal都是数组，则遍历key和newVal，更新组件的props
                  key.forEach((item, index) => {
                    updatedComponent.props[item as keyof AllComponentProps] =
                      newVal[index]
                  })
                } else if (
                  typeof key === 'string' &&
                  typeof newVal === 'string'
                ) {
                  // 如果key和newVal都是字符串，则更新组件的props
                  updatedComponent.props[key as keyof AllComponentProps] =
                    newVal
                }
              }
            }
            break
          }
          default: {
            break
          }
        }
        // 更新历史索引
        this.historyIndex++
        this.isAutoSave = true
        //设置组件层级
        this.setLayerZIndex()
      }
    },
    resetEditorStore() {
      this.historyList = []
      this.historyIndex = -1
      this.currentComponentId = ''
      this.testComponents = []
    },
  },
  getters: {
    CurrentComponent: (state) => {
      return state.testComponents.find(
        (item) => item.id === state.currentComponentId
      )
    },
    redoDisabled: (state) => {
      if (
        state.historyIndex === state.historyList.length ||
        state.historyIndex === -1 ||
        state.historyList.length === 0
      ) {
        return true
      } else {
        return false
      }
    },
    undoDisabled: (state) => {
      if (state.historyList.length === 0 || state.historyIndex === 0) {
        return true
      } else {
        return false
      }
    },
  },
})

export default useEditorStore

/**
 *  {
          id: uuidv4(),
          name: 'l-text',
          props: {
            ...textDefaultProps,
            text: 'hello',
            fontSize: '20px',
            width: '200px',
            height: '100px',
            left: '100px',
            top: '100px',
            position: 'absolute',
          },
          isHidden: false,
          isLocked: false,
          layerName: '图层1',
        },
        {
          id: uuidv4(),
          name: 'l-text',
          props: {
            ...textDefaultProps,
            text: 'hello2',
            fontSize: '100px',
            lineHeight: '1',
            fontFamily: 'Arial',
            fontWeight: 'bold',
            fontStyle: 'italic',
            textDecoration: 'underline',
          },
          isHidden: false,
          isLocked: false,
          layerName: '图层2',
        },
        {
          id: uuidv4(),
          name: 'l-text',
          props: {
            ...textDefaultProps,
            text: 'hello3',
            fontSize: '30px',
            lineHeight: '1',
            textAlign: 'left',
            fontFamily: '',
            color: '#fff777',
          },
          isHidden: false,
          isLocked: false,
          layerName: '图层3',
        },
        {
          id: uuidv4(),
          name: 'l-text',
          props: {
            ...textDefaultProps,
            text: 'hello4',
            fontSize: '40px',
            color: 'red',
          },
          isHidden: false,
          isLocked: false,
          layerName: '图层4',
        },
        {
          id: uuidv4(),
          name: 'l-text',
          props: {
            ...textDefaultProps,
            text: 'hello4',
            fontSize: '40px',
            color: 'red',
          },
          isHidden: false,
          isLocked: false,
          layerName: '图层5',
        },
 */
